iT邦幫忙

2025 iThome 鐵人賽

DAY 23
0
DevOps

不爆肝學習 Ansible 的短暫30天系列 第 23

Day23 - CI/CD 整合 Ansible 流程

  • 分享至 

  • xImage
  •  

今日目標

  • 了解 CI/CD 的核心概念與優勢
  • 掌握 Jenkins 與 Ansible 的整合應用
  • 建立完整的自動化部署流程

為什麼需要 CI/CD?

現如今開發流程中少不了測試驗證程式的正確性,但由於工程師身為一個懶人代表,不可能天天在那邊手動觸發測試,於是乎開始有了 CI (持續整合),簡單來說就是當我們 code commit 後會自動觸發的一整套流程。

那部署呢?大家可以想想如果今天上版頻率不低的情況下,如果部署不做自動化,那每次上版帶來的時間成本累積起來是非常可觀的一件事,所以這時候我們需要 CD (持續部署),來快速交付新功能。

那 Ansible 可以為 CI/CD 流程中帶來什麼樣的變化呢?前幾天有提到的,Ansible 可以幫助我們做到環境一致性,統一的部署流程,具有冪等性。

Jenkins 與 Ansible 整合

1. Jenkins 環境準備

安裝 Ansible 插件

# 在 Jenkins 中安裝 Ansible Plugin
# 管理 Jenkins → 管理插件 → 可用插件 → 搜尋 "Ansible"

配置 Ansible 工具

# 全域工具配置 → Ansible installations
# Name: ansible
# Path to ansible executables directory: /usr/local/bin/

2. Jenkins Pipeline 與 Ansible

筆者非常推薦如果是使用 Jenkins 的各位,請盡量使用 Jenkinsfile,搭配 groovy language 非常好用,大推

pipeline {
		// 如果各位有多台 instance 可以在這邊指定,或者運行在 docker 上都可以
    agent any

		// 定義環境變數
    environment {
        ANSIBLE_HOST_KEY_CHECKING = 'False'
        ANSIBLE_FORCE_COLOR = 'true'
    }

		// 設定 input 參數
    parameters {
        choice(
            name: 'ENVIRONMENT',
            choices: ['dev', 'staging', 'prod'],
            description: '選擇部署環境'
        )
        string(
            name: 'VERSION',
            defaultValue: 'latest',
            description: '應用程式版本'
        )
    }

    stages {
        stage('Checkout') {
            steps {
                git branch: 'main', url: '<https://github.com/your-org/ansible-playbooks.git>'
            }
        }

        stage('Lint Check') {
            steps {
                sh '''
                    ansible-lint playbooks/
                    yamllint .
                '''
            }
        }

        stage('Syntax Check') {
            steps {
                ansiblePlaybook(
                    playbook: 'playbooks/site.yml',
                    inventory: "inventories/${params.ENVIRONMENT}/inventory.ini",
                    extras: '--syntax-check'
                )
            }
        }

        stage('Deploy') {
            steps {
                ansiblePlaybook(
                    playbook: 'playbooks/site.yml',
                    inventory: "inventories/${params.ENVIRONMENT}/inventory.ini",
                    extras: "--extra-vars 'app_version=${params.VERSION}'",
                    credentialsId: 'ansible-vault-password'
                )
            }
        }

        stage('Verify Deployment') {
            steps {
                ansiblePlaybook(
                    playbook: 'playbooks/verify.yml',
                    inventory: "inventories/${params.ENVIRONMENT}/inventory.ini"
                )
            }
        }

        stage('Notify') {
            steps {
                script {
                    if (currentBuild.result == 'SUCCESS') {
                        slackSend(
                            color: 'good',
                            message: "✅ 部署成功: ${env.JOB_NAME} - ${params.ENVIRONMENT} - ${params.VERSION}"
                        )
                    } else {
                        slackSend(
                            color: 'danger',
                            message: "❌ 部署失敗: ${env.JOB_NAME} - ${params.ENVIRONMENT}"
                        )
                    }
                }
            }
        }
    }

    post {
        always {
            cleanWs()
        }
        failure {
            emailext(
                subject: "部署失敗: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
                body: "部署到 ${params.ENVIRONMENT} 環境失敗,請檢查 Jenkins 日誌。",
                to: "devops@company.com"
            )
        }
    }
}

3. 定期執行 Jenkins Job

# 將剛剛寫好的 Jenkinsfile 放到 Github 上面放,進行版本控制
# 建置觸發器,每五分鐘會去 Github 檢查
- GitHub hook trigger for GITScm polling
- Poll SCM: H/5 * * * *  # 每5分鐘檢查一次

# 部署方式很多種就看個人喜好去做設定,另外也可以透過 Github 進行版本控制,但手動在 Jenkins 上做觸發的動作

其他 CI/CD 的方式

藍綠部署 CI/CD 整合

Jenkins Pipeline 藍綠部署

stage('Blue-Green Deployment') {
    steps {
        script {
            // 部署到 Green 環境
            ansiblePlaybook(
                playbook: 'playbooks/blue-green-deploy.yml',
                inventory: "inventories/${params.ENVIRONMENT}/inventory.ini",
                extras: "--extra-vars 'target_color=green app_version=${params.VERSION}'"
            )

            // 健康檢查
            def healthCheck = ansiblePlaybook(
                playbook: 'playbooks/health-check.yml',
                inventory: "inventories/${params.ENVIRONMENT}/inventory.ini",
                extras: "--extra-vars 'target_color=green'"
            )

            if (healthCheck.result == 'SUCCESS') {
                // 切換流量到 Green
                ansiblePlaybook(
                    playbook: 'playbooks/switch-traffic.yml',
                    inventory: "inventories/${params.ENVIRONMENT}/inventory.ini",
                    extras: "--extra-vars 'active_color=green'"
                )

                // 停止 Blue 環境
                ansiblePlaybook(
                    playbook: 'playbooks/cleanup-blue.yml',
                    inventory: "inventories/${params.ENVIRONMENT}/inventory.ini"
                )
            } else {
                error("Health check failed, aborting deployment")
            }
        }
    }
}

實務小建議

1. 安全性最佳實務

  • 秘密管理:使用 Jenkins Credentials 或 Github Secrets 管理敏感資訊
  • 權限控制:不同環境使用不同的服務帳號和權限
  • 代碼掃描:整合安全掃描工具到 Pipeline 中
  • 稽核日誌:記錄所有部署活動和變更

2. 可靠性保證

  • 回滾機制:每次部署前準備快速回滾方案
  • 健康檢查:部署後自動驗證應用程式狀態
  • 漸進式部署:使用藍綠或金絲雀部署降低風險
  • 監控告警:部署後密切監控關鍵指標

3. 效能優化

  • 並行執行:合理使用 Pipeline 並行化提升效率
  • 快取機制:善用 Docker 層快取和依賴快取
  • 資源管理:適當分配 CI/CD 執行資源
  • 增量部署:只部署變更的組件

4. 團隊協作

  • 分支策略:建立清楚的 Git 分支和環境映射
  • 審核流程:生產環境部署需要人工審核
  • 通知機制:及時通知相關人員部署狀態
  • 文件維護:保持 Pipeline 配置和流程文件更新

作業練習時間

練習一:Jenkins Pipeline 設計

  1. 建立一個 Jenkins Declarative Pipeline
  2. 整合 Ansible Playbook 執行
  3. 添加參數化部署(環境、版本選擇)
  4. 設定部署後通知機制

練習二:藍綠部署實作

  1. 設計藍綠部署的 Ansible Playbook
  2. 整合到 CI/CD Pipeline 中
  3. 實作自動化健康檢查和流量切換
  4. 設計回滾機制

練習三:API 整合應用

  1. 在部署流程中整合 Slack 通知
  2. 實作與其他系統的 API 整合
  3. 設計部署狀態的監控和追蹤
  4. 建立部署 Dashboard

常見問題排查

Q1: Pipeline 執行權限問題

問題現象:

Permission denied (publickey)

解決方案:

  • 確認 SSH 金鑰已正確配置到 Jenkins
  • 檢查目標主機的 SSH 權限設定
  • 使用 ssh-agent 管理多個金鑰
  • 驗證 ansible_user 權限是否足夠

Q2: Ansible Vault 密碼問題

問題現象:

ERROR! Attempting to decrypt but no vault secrets found

解決方案:

  • 確認 Vault 密碼已設定為環境變數或檔案
  • 檢查 -vault-password-file 路徑是否正確
  • 使用 Jenkins Credentials 管理 Vault 密碼
  • 驗證 Vault 檔案是否已正確加密

Q3: 部署卡住或超時

問題現象:
Pipeline 執行時間過長或無響應

解決方案:

  • 設定適當的超時時間
  • 檢查網路連接和防火牆設定
  • 使用 asyncpoll 處理長時間任務
  • 優化 Playbook 執行效率

Q4: 環境間配置衝突

問題現象:
不同環境的部署結果不一致

解決方案:

  • 檢查環境變數和 group_vars 配置
  • 確保 Inventory 檔案正確分離
  • 使用條件判斷處理環境差異
  • 建立環境配置驗證機制

明日預告

明天來聊聊監控


上一篇
Day22 - Ansible 要如何有效管理多個環境呢?
下一篇
Day24 - 監控做得好,晚上就睡好
系列文
不爆肝學習 Ansible 的短暫30天24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言